package xcmg.device.web.file;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import xcmg.device.dao.entity.file.FileRecord;
import xcmg.device.infra.BasicController;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.exception.CommonBusiExceptions;
import xcmg.device.service.file.FtpService;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;


@Controller
@RequestMapping("/ftp")
@Api(value = "ftp图片上传--Controller ")
@Slf4j
public class FtpController extends BasicController {

    @Value("${file.upload.path:/home/upload/}")
    private String path;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private FtpService ftpService;

    private static final Integer FORBID_PNG = 0;

    /**
     * @param imgSize    可选，图片尺寸，格式（宽*高）如 200*200
     * @param isAllowPng 1 允许PNG图片上传，默认允许（PNG不支持压缩，大部分业务场景不适用）
     * @param imgFile    图片
     * @return
     */
    @PostMapping("/uploadImg")
    @ResponseBody
    public ActionResult<FileRecord> uploadImg(@RequestParam(required = false) @ApiParam("格式,如 200*200") String imgSize, @RequestParam(defaultValue = "1") Integer isAllowPng, @RequestParam("imgFile") MultipartFile imgFile) {

        File dir = null;
        FileRecord imageDesc = new FileRecord(imgFile.getOriginalFilename());
        String url = null;
        try {
            dir = new File(new File(path).getAbsolutePath() + File.separator);
            if (!dir.exists()) {
                log.info(" create dir " + dir.getAbsolutePath());
                boolean r = dir.mkdirs();
                log.info(" create dir return " + r);
            }
            url = this.uploadingFile(imgFile, dir.getAbsolutePath(), imgSize, isAllowPng, true);
            imageDesc.setImageUrl(url);
        } catch (Exception e) {
            log.error("", e);
            throw new CommonBusiExceptions(ErrorCode.FtpUploadError.getDesc());
        } finally {
            if (dir != null) {
                boolean r = dir.delete();
                log.info(" delete dir return " + r);
            }
        }
        if (StringUtils.isNotBlank(url)) {
            imageDesc.setImageUrl(url);
            return actionValueResult(imageDesc);
        } else {
            throw new CommonBusiExceptions(ErrorCode.FtpUploadError.getDesc());
        }
    }


    @PostMapping("/uploadFile")
    @ResponseBody
    public ActionResult<FileRecord> uploadFile(@RequestParam("file") MultipartFile file) {
        File dir = null;
        FileRecord imageDesc = new FileRecord(file.getOriginalFilename());
        String url = null;
        try {
            dir = new File(new File(path).getAbsolutePath() + File.separator);
            if (!dir.exists()) {
                log.info(" create dir " + dir.getAbsolutePath());
                boolean r = dir.mkdirs();
                log.info(" create dir return " + r);
            }
            url = this.uploadingFile(file, dir.getAbsolutePath(), null, null, false);
            imageDesc.setImageUrl(url);
        } catch (Exception e) {
            log.error(" Exception ", e);
            throw new CommonBusiExceptions(ErrorCode.FtpUploadError.getDesc());
        } finally {
            if (dir != null) {
                boolean r = dir.delete();
                log.info(" delete dir return " + r);
            }
        }
        if (StringUtils.isNotBlank(url)) {
            imageDesc.setImageUrl(url);
            return actionValueResult(imageDesc);
        } else {
            throw new CommonBusiExceptions(ErrorCode.FtpUploadError.getDesc());
        }
    }

    /**
     * 上传单张图片, 图片基本格式校验
     *
     * @return 上传nos后返回的url
     */
    private String uploadingFile(MultipartFile multipartFile, String filePath, String imgSize, Integer isAllowPng, boolean image) {
        String url = "";
        File tmpFile = null;
        try {
            if (image) {
                String type = multipartFile.getContentType();
                if (StringUtils.isBlank(type) || !type.startsWith("image/")) {
                    throw new CommonBusiExceptions("上传文件类型有误");
                }
            }
            String originalName = multipartFile.getOriginalFilename();

            //生成唯一键
            ActionResult<String> textResult = fastGenClient.textGuid();
            if (textResult.getCode() != ErrorCode.Success.getCode()) {
                throw new CommonBusiExceptions("获取图片主键失败");
            }

            String fileName = "U_" + textResult.getValue() + multipartFile.getOriginalFilename().substring(originalName.lastIndexOf("."));
            tmpFile = new File(filePath + File.separator + fileName);
            multipartFile.transferTo(tmpFile);
            if (image) {
                if (!this.validateImageSize(tmpFile, imgSize)) {
                    throw new CommonBusiExceptions("图片上传失败：图片不符规格！");
                }
                if (tmpFile.getName().toLowerCase().contains(".png") && FORBID_PNG.equals(isAllowPng)) {
                    throw new CommonBusiExceptions("不支持png图片");
                }
            }
            url = ftpService.uploadFile(tmpFile, null);
            if (StringUtils.isBlank(url)) {
                log.error(" upload file  urlis blank ");
                throw new CommonBusiExceptions("文件上传处理异常");
            }
            log.info(" upload file {}",  url);
        } catch (Exception e) {
            log.error(" upload file {}", url, e);
            log.error("文件上传处理异常", e);
        } finally {
            if (tmpFile != null) {
                boolean r = tmpFile.delete();
                log.info(" delete local file return " + r);
            }
        }
        return url;
    }

    /**
     * @param file    图片
     * @return
     */
    @GetMapping("/downloadFile")
    @ResponseBody
    public void downloadFile(@RequestParam("file") String file, HttpServletResponse response) {
        if (null != file && file.startsWith("root")) {
            file = file.substring(4);
        }
        try {
            int index = file.lastIndexOf("/");
            if (file.length() > 1 && index > 0) {
                String fileName = file.substring(index + 1);
                //设置响应头的打开方式
                response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
                ftpService.downloadFile(file.substring(0, index),fileName, response.getOutputStream());
            }
        } catch (Exception e) {
            log.error("", e);
        }
    }


    /**
     * 图片尺寸校验
     *
     * @param f       图片文件
     * @param imgSize 文件大小
     */
    private boolean validateImageSize(File f, String imgSize) throws IOException {
        String checkImgSize = imgSize;
        if (f == null) {
            return false;
        }
        // imgSize为空，表示不需校验
        if (StringUtils.isBlank(checkImgSize)) {
            return true;
        }

        //两个星号不好处理，把开头和结尾的先转换为#号，再处理
        checkImgSize = checkImgSize.replaceAll("^\\*|\\*$", "#");
        String[] imgSizeArr = checkImgSize.split("\\*");
        if (imgSizeArr.length != 2) {
            throw new CommonBusiExceptions("图片大小格式不对");
        }
        Integer[] imageWidthHeight = new Integer[imgSizeArr.length];
        // 读取原图长宽设置
        BufferedImage buff = ImageIO.read(f);

        if (buff == null) {
            log.info("validateImageSize buff is null,  checkImgSize = " + checkImgSize);
            return false;
        }
        int width = buff.getWidth();
        int height = buff.getHeight();

        if ("#".equals(imgSizeArr[0])) {
            imageWidthHeight[0] = width;
        } else {
            imageWidthHeight[0] = Integer.parseInt(imgSizeArr[0]);
        }

        if ("#".equals(imgSizeArr[1])) {
            imageWidthHeight[1] = height;
        } else {
            imageWidthHeight[1] = Integer.parseInt(imgSizeArr[1]);
        }

        int w = imageWidthHeight[0];
        int h = imageWidthHeight[1];

        return width == w && height == h;
    }
}
